10章 マップとセット
https://gyazo.com/51ba590422cb6160a4960060509a9941
10.1 マップ(Map)
ES2015から追加
キーと値の間の対応関係が必要な場合にオブジェクトを使う問題点
オブジェクトにはプロトタイプがあるため、意図しないマッピングが生じる危険性がある
オブジェクトではキーと値の組がいくつあるのか簡単にわからない
キーは文字列あるいはシンボルに限られる
オブジェクトをキーとして値と対応づけることができない
Mapオブジェクトには上のような問題はない
数学的なマップ(写像)は2つの集合があるときに一方の各要素に対し、他方のただ一つの要素を結びつける対応のことを言う。 code:js
const u1 = { name: '和洋' };
const u2 = { name: '花子' };
const u3 = { name: '涼子' };
const u4 = { name: '哲人' };
// Mapオブジェクトの生成
const userRoles = new Map();
// 対応づけ
// userRoles.set(u1, 'ユーザー');
// userRoles.set(u2, 'ユーザー');
// userRoles.set(u3, '管理者');
// setメソッドはチェイン可能
userRoles
.set(u1, 'ユーザー');
.set(u2, 'ユーザー');
.set(u3, '管理者');
コンストラクタに配列の配列を渡してMapを初期化することもできる
code:js
const userRoles = new Map([
]);
メソッドgetで値を取得、hasでマップにキーが含まれているか確認できる。
code:js
console.log(userRoles.has(u1)); // true
console.log(userRoles.get(u1)); // ユーザー
console.log(userRoles.has(u4)); // false
console.log(userRoles.get(u4)); // undefiined
マップにすでに存在しているキーに対してsetを行うと値が置換される
プロパティsizeで何組の対応があるかがわかる
code:js
console.log(userRoles.size); // 3
keys: マップ内のすべてのキーを取得
values: マップ内のすべての値を取得
entries: マップ内のすべてのエントリ(対応関係)を取得
エントリは配列のような形式で出力され、最初の要素がキー、次の要素が値になる
この3つのメソッドはfor...ofループで利用可能なイテレーション可能なオブジェクトを返す
配列が欲しい場合はスプレッド演算子(6章 関数参照)が使える delete: マップから一つの要素を削除する
clear: すべてのエントリを削除する
10.3 ウィークマップ(WeakMap)
WeakMapオブジェクトはマップと似ているが次の点が異なる
キーはオブジェクトでなければならない
キーがガベージコレクションの対象になる
イテレーションしたりクリアしたりできない
通常JavaScriptの処理系はどこかから参照がある限りオブジェクトをメモリ内に保持している
ウィークマップに関してはこれは保証されない
このため、イテレーションできない。ガベージコレクションの中のオブジェクトに対してイテレーションするのは危険が伴う。
ウィークマップはオブジェクトのインスタンスに対して、外から操作不可能なプライベートキーを保管するのに利用することができる
code:js
const SecretHolder = (function() {
const secrets = new WeakMap();
retur class {
setSecret(secret) {
secrets.set(this, secret);
}
getSecret() {
return secrets.get(this);
}
}
})();
マップを利用することもできるが、そうするとインスタンスに渡す秘密はガベージコレクションの対象にならなくなる。
10.3 セット(Set)
セットは重複が許されないデータの集合
code:js
const roles = new Set();
roles.add("ユーザー");
console.log(roles); // Set { 'ユーザー' }
roles. add("管理者");
console.log(roles); // Set { 'ユーザー', '管理者' }
// マップと同様にプロパティ size をもつ
console.log(roles.size); // 2
// すでに追加されているものを追加しても何も起こらない
roles.add("ユーザー");
console.log(roles); // Set { 'ユーザー', '管理者' }
console.log(roles.delete("管理者")); // true
console.log(roles); // Set { 'ユーザー' }
console.log(roles.delete("管理者")); // false
10.4 ウィークセット(WeakSet)
オブジェクトだけを含むことができるセットで、オブジェクトがガベージコレクションの対象となる可能性がある
ウィークセットの値はイテレーションできない
ウィークセットを利用したくなる唯一の場面と思われるのは、指定のオブジェクトがあるセットにあるかどうかを決定すること
code:js
const naughty = new WeakSet();
const children = [
{ name: "和洋" },
{ name: "哲人" },
];
for(let child of children) {
if(naughty.has(child))
console.log(${child.name}クンには石炭をあげる!);
else
console.log(${child.name}クンにはプレゼントをあげる!);
}
/* 実行結果
和洋クンにはプレゼントをあげる!
哲人クンには石炭をあげる!
*/
10.5 オブジェクトかマップか
オブジェクトを使おうと考えたらマップとセットが使えないかを考える癖をつける